﻿namespace Atomic.Modules.Security
{
    using System;
    using System.Web;
    using System.Web.Security;

    /// <summary>
    /// 认证服务。
    /// </summary>
    public class AuthenticationService : IAuthenticationService
    {
        /// <summary>
        /// 会员服务。
        /// </summary>
        private readonly IMembershipService _membershipService = null;

        /// <summary>
        /// 初始化认证服务。
        /// </summary>
        /// <param name="membershipService">会员服务。</param>
        public AuthenticationService(IMembershipService membershipService)
        {
            this._membershipService = membershipService;

            //间隔 14 天。
            this.ExpirationTimeSpan = new TimeSpan(14, 0, 0, 0);
        }

        /// <summary>
        /// 过期时间时隔。
        /// </summary>
        public TimeSpan ExpirationTimeSpan { get; set; }

        /// <summary>
        /// 登录。
        /// </summary>
        /// <param name="user">已验证成功的用户信息。</param>
        /// <param name="createPersistentCookie"></param>
        public void SignIn(IUser user, bool createPersistentCookie)
        {
            if (user == null)
            {
                throw new ArgumentNullException("user", "获得用户信息失败。");
            }

            DateTime now = DateTime.Now;

            var userData = user.Id + "|" + user.Account.AccountNumber;

            var ticket = new FormsAuthenticationTicket(
                1 /*version*/,
                user.Name,
                now,
                now.Add(ExpirationTimeSpan),
                createPersistentCookie,
                userData,
                FormsAuthentication.FormsCookiePath);

            var encryptedTicket = FormsAuthentication.Encrypt(ticket);

            var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
            cookie.HttpOnly = true;
            cookie.Secure = FormsAuthentication.RequireSSL;
            cookie.Path = FormsAuthentication.FormsCookiePath;
            if (FormsAuthentication.CookieDomain != null)
            {
                cookie.Domain = FormsAuthentication.CookieDomain;
            }

            if (createPersistentCookie)
            {
                cookie.Expires = ticket.Expiration;
            }

            var httpContext = HttpContext.Current;

            httpContext.Response.Cookies.Add(cookie);
        }

        /// <summary>
        /// 登出。
        /// </summary>
        public void SignOut()
        {
            FormsAuthentication.SignOut();
        }

        /// <summary>
        /// 获得已认证的用户。
        /// </summary>
        /// <remarks>
        /// 该方法获得的是已登录的用户，如果是未登录的，则返回 AnonymousUser 类的实例。
        /// </remarks>
        /// <returns>用户实体。</returns>
        public IUser GetAuthenticatedUser()
        {
            var httpContext = HttpContext.Current;
            if (httpContext == null || !httpContext.Request.IsAuthenticated || !(httpContext.User.Identity is FormsIdentity))
            {
                return this._membershipService.GetAnonymousUser();
            }

            IUser user = this._membershipService.GetUserByAccountNumber(httpContext.User.GetCurrentAccountNumber());

            if (user == null)
            {
                user = this._membershipService.GetAnonymousUser();
            }

            return user;
        }
    }
}